package com.ctl.jvm;

import java.util.Random;
import java.util.concurrent.Exchanger;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * Exchanger用于线程间进行通信、数据交换。Exchanger提供了一个同步点exchange方法，
 * 两个线程调用exchange方法时，无论调用时间先后，两个线程会互相等到线程到达exchange方法调用点，
 * 此时两个线程可以交换数据，将本线程产出数据传递给对方
 */
public class Exchanger2Test {
    static class Producer extends Thread {
        private Exchanger<Integer> exchanger;
        private static int data = 0;
        private Object obj;
        Producer(String name, Exchanger<Integer> exchanger, Object obj) {
            super("Producer-" + name);
            this.exchanger = exchanger;
            this.obj=obj;
        }

        @Override
        public void run() {
            for (int i=1; i<5; i++) {
                try {
//                    TimeUnit.MILLISECONDS.sleep(new Random().nextInt(1000));
                    data = i;
obj.wait();
                    try {
                     int a= exchanger.exchange(data,1000,TimeUnit.MILLISECONDS);
                        System.err.println(a);

                    } catch (TimeoutException e) {
                        e.printStackTrace();
                    }
                    System.out.println("bar");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    static class Consumer extends Thread {
        private Exchanger<Integer> exchanger;
        private static int data = 0;
        private Object obj;

        Consumer(String name, Exchanger<Integer> exchanger,Object obj) {
            super("Consumer-" + name);
            this.exchanger = exchanger;
            this.obj=obj;

        }

        @Override
        public void run() {
            for (int i=1; i<5; i++) {
                try {
//                    TimeUnit.MILLISECONDS.sleep(new Random().nextInt(1000));
                    data = i;
                    System.out.print("foo");
                    try {
                      int a= exchanger.exchange(data,1000,TimeUnit.MILLISECONDS);
                      obj.notifyAll();
                        System.err.println(a);
                    } catch (TimeoutException e) {
                        e.printStackTrace();
                    }                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Exchanger<Integer> exchanger = new Exchanger<>();
        Object obj =new Object();
        new Producer("", exchanger,obj).start();
        new Consumer("", exchanger,obj).start();
        TimeUnit.SECONDS.sleep(5);
        System.exit(-1);
    }
}